package com.googlecode.groovy_toy_orm

import com.googlecode.groovy_toy_orm.internal.Util

/**
 * @author: DavydovMD
 * Date: 11.04.13
 * Time: 12:22
 */
class MultiMapper extends Mapper {
    private List<Mapper> mappers;

    /**
     * getter for mappers
     * @return The only reason for returning List instead List<Mapper> is a bug in IDEA: http://youtrack.jetbrains.com/issue/IDEA-106374
     */

    public List getMappers(){
        mappers
    }


    protected void setMappers(List<Mapper> mappers){
        this.mappers = mappers;
    }

    protected final Map<String, Mapper> fieldsMappers = new HashMap<>()


    MultiMapper(List<Mapper> mappers, String keyField = null) {
        super(null as MapperFields)
        MapperFields multiBuilder = new MapperFields()


        this.mappers = mappers.asImmutable()

        //init fieldMappers
        for (Mapper mapper in mappers) {
            multiBuilder.add(mapper.builder.copy(mapper.getPrefix()))

            mapper.getAllFields().each { Field f ->
                if (!fieldsMappers.containsKey(f.name)) {
                    fieldsMappers.put(f.name, mapper)
                }
            }
        }

        this.builder = multiBuilder
        if (!keyField)
            this.keyField = builder.fields.first().name
        else
            this.keyField = keyField
    }


    public Mapper mapperByPrefix(String prefix) {
        mappers.find {
            it.getPrefix() == prefix
        }
    }


    //TODO: test!!!!
    public Mapper findMapper(String field) {
        builder.getField(field) //Check that field is present first!
        String simpleName =  Field.simplifyName(field) // Checks that field is known
        //Todo: method to calculate prefix. We must not calculate it directly!!!
        String prefix = field == simpleName ? "" : Util.cutLastToken(field)

        Mapper m = fieldsMappers.get(simpleName) //

        if (prefix && prefix != m.getPrefix()) {
            return mapperByPrefix(prefix)
        }

        if (!m)
            throw new NoSuchFieldException("Field not found:${field}?")
        m

    }

    @Override
    Object transformBackFieldValue(String field, Object value) {
        return findMapper(field).transformBackFieldValue(Field.simplifyName(field), value)    //To change body of overridden methods use File | Settings | File Templates.
    }

    @Override
    Object getSourceName(String field) {
        return findMapper(field).getSourceName(Field.simplifyName(field))    //To change body of overridden methods use File | Settings | File Templates.
    }


    @Override
    String getFqSourceName(String field) {
        return findMapper(field).getFqSourceName(Field.simplifyName(field))    //To change body of overridden methods use File | Settings | File Templates.
    }

    @Override
    public Map<String, String> getFqSourceNames(String field) {
        return findMapper(field).getFqSourceNames(Field.simplifyName(field))
    }

    @Override
    public String toString() {
        "MultiMapper of mappers: ${mappers} (key:$keyField)"
    }

    @Override
    Field getField(String fieldName) {
        //TODO: add support for fully qualified field names -> return appropriate mapper
        Mapper m = findMapper(fieldName)


        if (!m) throw new NoSuchFieldException("No such field found: ${fieldName} in mapper ${this}")

        m.getField(Field.simplifyName(fieldName))    //To change body of overridden methods use File | Settings | File Templates.
    }


}
